﻿using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WH.Common.UniOfWork
{
    public interface IUnitOfWork
    {
        ITenant GetDbClient();

        Task BeginTranAsync();

        Task CommitTranAsync();

        Task RollbackTranAsync();
    }


    public class UnitOfWork : IUnitOfWork
    {
        //private readonly object unitOfWorkLock = new object();

        private static SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);

        private readonly ISqlSugarClient _sqlSugarClient;

        private int _tranCount { get; set; }

        //
        // 参数:
        //   dbContext:
        public UnitOfWork(ISqlSugarClient dbContext)
        {
            _sqlSugarClient = dbContext;
            _tranCount = 0;
        }

        //
        // 摘要:
        //     获取DB，保证唯一性
        public ITenant GetDbClient()
        {
            return _sqlSugarClient as ITenant;
        }

        public async Task BeginTranAsync()
        {
            await semaphore.WaitAsync();
            try
            {
                _tranCount++;
                await GetDbClient().BeginTranAsync();
            }
            finally
            {
                semaphore.Release();
            }
        }

        public async Task CommitTranAsync()
        {
            await semaphore.WaitAsync();
            try
            {
                _tranCount--;
                if (_tranCount == 0)
                {
                    try
                    {
                        await GetDbClient().CommitTranAsync();
                        return;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                        await GetDbClient().RollbackTranAsync();
                        return;
                    }
                }
            }
            finally
            {
                semaphore.Release();
            }
        }

        public async Task RollbackTranAsync()
        {
            await semaphore.WaitAsync();
            try
            {
                _tranCount--;
                await GetDbClient().RollbackTranAsync();
            }
            finally
            {
                semaphore.Release();
            }
        }

    }
}

